home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DBio / DREnzyme.cpp < prev    next >
Text File  |  1996-07-05  |  45KB  |  1,790 lines

  1. // DREnzyme.cp
  2. // d.g.gilbert
  3.  
  4.  
  5. #include <ncbi.h>
  6. #include <dgg.h>
  7. #include <DFile.h>
  8. #include <DList.h>
  9. #include <DApplication.h>
  10. #include <DWindow.h>
  11. #include <DControl.h>
  12. #include <DPanel.h>
  13. #include <DUtil.h>
  14. #include "DSequence.h"
  15. #include "DREnzyme.h"
  16. #include <DDialogText.h>
  17.  
  18. #define EDITTABLE
  19.  
  20.  
  21.  
  22. class DREnzymeGlobals {
  23. public:
  24.    DREnzymeGlobals() 
  25.        { 
  26.        DCodons::Initialize();
  27.        //DREMap::Initialize();
  28.        }
  29. };
  30.  
  31. static DREnzymeGlobals    globals; // initializes globals here
  32. extern Nlm_FonT  Nlm_fontInUse;
  33. extern "C" void Nlm_TextEnableNewlines(Nlm_TexT t, Nlm_Boolean turnon);
  34.  
  35.  
  36.  
  37.     // ?? use hash table for codons, other table lookups !?
  38. static long Hash( char    *s)
  39. {
  40.     register char    c;
  41.     register long    val = 0;
  42.     while ((c = *s++) != '\0') val += (int) tolower(c);
  43.     return (val);
  44. }
  45.  
  46.  
  47. // class DLocateFile
  48.  
  49. class DLocateFile : public DWindow {
  50. public: 
  51.     char * fName;
  52.     DLocateFile(char* fname, char* desc);    
  53.     ~DLocateFile();
  54.     void OkayAction();
  55. };
  56.         
  57.         
  58. DLocateFile::DLocateFile(char* format, char* name) :
  59.     DWindow( 0, gApplication, fixed, -10, -10, -50, -20, "Locate data", kDontFreeOnClose)
  60. {
  61.     char buf[512];
  62.     DView* super = this;
  63.  
  64.     fName= StrDup(name);
  65.     sprintf(buf, format, name);
  66.     new DNotePanel(0, super, buf, 280, 50);    
  67.     this->NextSubviewBelowLeft();
  68.     new DPrompt( 0, super, "Would you like to locate it?", 280);
  69.     this->NextSubviewBelowLeft();
  70.     this->AddOkayCancelButtons(cOKAY,"Locate",cCANC,"Cancel");
  71. }
  72.  
  73. DLocateFile::~DLocateFile()
  74. {
  75.     MemFree( fName);
  76. }
  77.  
  78. void DLocateFile::OkayAction() 
  79.     DWindow::OkayAction();
  80.     char * suffix= (char*) DFileManager::FileSuffix( fName);
  81.     char * name= (char*) DFileManager::GetInputFileName( suffix, "TEXT");
  82.     MemFree( fName);
  83.     fName= StrDup( name);
  84. }
  85.  
  86.  
  87.  
  88. // class DReplaceFileDlog
  89.  
  90. class DReplaceFileDlog : public DWindow {
  91. public: DReplaceFileDlog(char* title);
  92. };
  93.  
  94. DReplaceFileDlog::DReplaceFileDlog(char* title) :
  95.     DWindow( 0, NULL, DWindow::modal, -10, -10, -50, -20, "", kDontFreeOnClose) // DWindow::fixed
  96. {
  97.     char str[128];
  98.     if (title && *title)  
  99.         sprintf( str, "Replace file '%s'?", title);
  100.   else
  101.       StrCpy( str, "Replace this file?");
  102.     new DPrompt( 0, this, str, 0, 0, Nlm_systemFont);             
  103.     this->AddOkayCancelButtons(cOKAY,"Yes",cCANC,"No");    
  104.     DWindow::Open();
  105. }
  106.  
  107.  
  108.  
  109.  
  110. // class DTableChoiceDialog
  111.  
  112. class DTableChoiceDialog : public DWindow {
  113. public: 
  114.     enum { 
  115.         cSetDefault = 3225, cChoose, cSave,
  116.         kEditNone= 0, kEditOpen, kEditChanged
  117.         };
  118.     DPrompt    * fName;
  119.     DFile    * fFile;
  120.     Boolean fSetPref;
  121.     short fEditData;
  122.     ulong fEditLen;
  123.     long    fEditChk;
  124.     DDialogScrollText* fText;
  125.     
  126.     DTableChoiceDialog(char* title, char* desc=NULL, char* curfile = NULL);    
  127.     ~DTableChoiceDialog();        
  128.     Nlm_Boolean IsMyAction(DTaskMaster* action);
  129.     void OkayAction();
  130.     Boolean OpenText();
  131. };
  132.         
  133.     
  134. DTableChoiceDialog::DTableChoiceDialog(char* title, char* desc, char* curfile) :
  135.     DWindow( 0, gApplication, fixed, -10, -10, -50, -20, title, kDontFreeOnClose),
  136.     fFile(NULL), fName(NULL), fSetPref(false), fEditData(kEditNone), fEditChk(0),
  137.     fText(NULL)
  138. {
  139.     enum { cluwidth= 430 };
  140.     DCluster* clu;
  141.     DView* super;
  142.  
  143.     if (curfile) fFile= new DFile(curfile,"r"); // in case user wants default !
  144.  
  145.     if (desc) {
  146.         char buf[128];
  147.         sprintf(buf, "%s data", title);
  148.         clu= new DCluster( 0, this, 0, 0, false, buf);   
  149.         if (clu) super= clu; else super= this;
  150. #ifdef EDITTABLE
  151.         DDialogScrollText* dt= new DDialogScrollText( 0, super, 50, 15, gTextFont, false);
  152.         fText= dt;
  153.         //Nlm_TextEnableNewlines( dt->fText, true);
  154.         if (!OpenText()) {
  155.             fText->SetText( desc);  
  156.             fText->Disable();// make fText un-editable...
  157.             sprintf(buf, "%s format", title);
  158.             clu->SetTitle( buf);
  159.             }
  160. #else
  161.         new DNotePanel(0, super, desc, cluwidth, 120);    
  162. #endif
  163.         this->NextSubviewBelowLeft();
  164.         }
  165.  
  166.     clu= new DCluster( 0, this, 0, 0, false, "Current table");   
  167.     if (clu) super= clu; else super= this;
  168.     fName= new DPrompt( 0, super, curfile, cluwidth);
  169.     this->NextSubviewBelowLeft();
  170.  
  171.     new DButton( cChoose, this, "Choose file");
  172.     this->NextSubviewToRight();
  173.     new DCheckBox( cSetDefault,this,"Make this default table");
  174.     this->NextSubviewBelowLeft();
  175.     this->AddOkayCancelButtons(cOKAY,"Okay",cCANC,"Cancel");
  176. }
  177.  
  178. DTableChoiceDialog::~DTableChoiceDialog()
  179. {
  180.     if (fFile) delete fFile;
  181. }
  182.  
  183. Boolean DTableChoiceDialog::OpenText() 
  184. {
  185.     Boolean okay= false;
  186.     fEditData= kEditNone;
  187.             // use "rb" to avoid newline translation !!
  188.     if (fText && fFile->Open("rb") == 0) {
  189.         ulong len= fFile->LengthF();
  190.         
  191.                 // check for overly long files!? (10K is big...)
  192.                 // REnzyme.table is too big !! (>32k)
  193.         if (len>10000) return false; // quick fix...
  194.         
  195.         char* buf= (char*) MemNew( len+1);
  196.             // Damn codewarrior stdio is translating mac newline to unix newline here!!
  197.         fFile->ReadData( buf, len);
  198.         fFile->Close();
  199.         buf[len]= 0;
  200.         fEditData= kEditOpen;
  201.         fEditLen= len;
  202.         fEditChk= Hash( buf);
  203.         
  204.         fText->SetText( buf);  
  205.         fText->Enable(); 
  206.         MemFree( buf);
  207.         okay= true;
  208.         }
  209.     return okay;
  210. }
  211.  
  212.  
  213. Nlm_Boolean DTableChoiceDialog::IsMyAction(DTaskMaster* action) 
  214. {    
  215.     switch(action->Id()) {
  216.         case cSave:
  217.             return true;
  218.             
  219.         case cChoose:
  220.             if (fFile) delete fFile;
  221.             if (gApplication->ChooseFile( fFile, NULL, "TEXT")) { 
  222.               fName->SetTitle( (char*)fFile->GetName());
  223. #ifdef EDITTABLE
  224.               if (!OpenText()) ;
  225. #else
  226.               gApplication->OpenDocument( fFile); // view it ??
  227. #endif
  228.               }
  229.             return true;
  230.             
  231.         default:
  232.             return DWindow::IsMyAction(action);    
  233.         }
  234. }
  235.  
  236.  
  237.  
  238. void DTableChoiceDialog::OkayAction() 
  239.     DWindow::OkayAction();
  240.     DCheckBox* ck = (DCheckBox*) this->FindSubview(cSetDefault);
  241.     if (ck && ck->GetStatus() && fFile && fFile->Exists()) {
  242.         fSetPref= true; 
  243.         }
  244.         
  245. #ifdef EDITTABLE
  246.     if (fFile && fText && fEditData >= kEditOpen) {
  247.         Boolean okay= true;
  248.         char *buf= fText->GetText();
  249.         ulong len= StrLen(buf);
  250.         if (len == fEditLen) {
  251.             long check= Hash( buf);
  252.             if (check == fEditChk) return;
  253.             }
  254.         // ask user if s/he wants to save it...
  255.         if (fFile->Exists()) {
  256.             DReplaceFileDlog* dlog= new DReplaceFileDlog( (char*)fFile->GetName());
  257.             okay= dlog->PoseModally();
  258.              delete dlog;  
  259.              if (!okay) {
  260.                 //if (fFile) delete fFile;
  261.                 const char* newname= gFileManager->GetOutputFileName(fFile->GetShortname());
  262.                 if (newname) { 
  263.                     fFile->SetName( newname);
  264.                     //if (fFile->Exists()) fFile->Delete(); //??
  265.                   //fName->SetTitle( (char*)fFile->GetName());
  266.                   //if (!OpenText()) ;
  267.                   }
  268.               }
  269.             }
  270.         if (okay) {
  271.             //fFile->Delete(); // need this !?
  272.             if (fFile->Exists()) {
  273.                 char newname[512];
  274.                 StrNCpy(newname, fFile->GetName(), sizeof(newname));
  275.                 DFileManager::ReplaceSuffix( newname, sizeof(newname), ".old");
  276.                 DFileManager::Rename( fFile->GetName(), newname);
  277.                 }
  278.             fFile->Open("wb");
  279.             fFile->WriteData( buf, len);
  280.             fFile->Close();
  281.             }
  282.         }
  283. #endif        
  284. }
  285.  
  286.  
  287.     
  288. inline char* FlushLine( char* cp)
  289. {
  290.     char * ep;
  291.     while (*cp  && *cp <= ' ') cp++;
  292.     ep= StrChr(cp, '\0') - 1;
  293.     while (ep >= cp && *ep <= ' ') ep--;
  294.     ep[1]= 0;
  295.     //ep= StrChr(cp, ' '); if (ep) *ep= 0;
  296.     return cp;
  297. }
  298.  
  299.  
  300.  
  301.  
  302. #if 0
  303. // this isn't useful till we revise subclasses to be non-statics         
  304. // class DDataTable    
  305.  
  306. Nlm_Boolean DTableClass::NotAvailable()
  307. {
  308.     if (fState == kUnread) {
  309.         char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  310.         if (tablefile) ReadTable( tablefile);
  311.         else fState= kNodata;
  312.         if (fState != kOkay) Message(MSG_OK,"Could not read table file '%s'",tablefile);
  313.         }
  314.     return (fState != kOkay);
  315. }
  316.  
  317. void DTableClass::Initialize(char* type, char* section, char* defaultvalue)
  318. {
  319.     fState= kUnread;
  320.     fType= type;
  321.     fSection= section;
  322.     fDefaultvalue= defaultvalue;
  323. }
  324.  
  325. void DTableClass::ReadTable( char* tableFile)
  326. {
  327.      DFile aFile( tableFile, "r");
  328.     ReadTable( &aFile);
  329. }
  330.  
  331. //void DTableClass::TableChoice() = 0;
  332. //void DTableClass::ReadTable(DFile* aFile) = 0
  333.  
  334. #endif
  335.  
  336.  
  337.  
  338.  
  339.  
  340.     
  341. // struct CodonStat    
  342.     
  343. CodonStat::CodonStat( char* codn, char ami, float numk):
  344.     amino(ami), numPerK( numk)
  345. {
  346.     if (!codn) codn= "---";
  347.     codon[0]= codn[0]; 
  348.     codon[1]= codn[1]; 
  349.     codon[2]= codn[2]; 
  350.     codon[3]= codn[3]; 
  351. }     
  352.          
  353.          
  354. // class DCodons    
  355.  
  356. short DCodons::fState= DCodons::kUnread;
  357. short DCodons::fStartcodon= -1;
  358. CodonStat* DCodons::fCodons= NULL;
  359. char* DCodons::fType= "codon";
  360. char* DCodons::fSection= "data";
  361. char* DCodons::fDefaultvalue= "tables:codon.table";
  362.  
  363. Nlm_Boolean DCodons::NotAvailable()
  364. {
  365.     if (fState == kUnread) {
  366.         char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  367.         if (tablefile) {
  368.             ReadTable( tablefile);
  369.             if (fState != kOkay) {
  370.                 // dialog - would you like to locate data?
  371.                 DLocateFile* win= new DLocateFile("Could not read table file '%s'", tablefile);
  372.                 if (win->PoseModally()) {
  373.                     ReadTable( win->fName);
  374.                     if (fState == kOkay)
  375.                         gApplication->SetPref( win->fName, fType, fSection); //??
  376.                     }
  377.                 delete win;
  378.                 }
  379.             }
  380.         else 
  381.             fState= kNodata;
  382.         if (fState != kOkay)
  383.              Message(MSG_OK,"Could not read table file '%s'",tablefile);
  384.         MemFree( tablefile);
  385.         }
  386.     return (fState != kOkay);
  387. }
  388.  
  389. void DCodons::Initialize(char* type, char* section, char* defaultvalue)
  390. {
  391.     fState= kUnread;
  392.     fType= type;
  393.     fSection= section;
  394.     fDefaultvalue= defaultvalue;
  395.     if (fCodons==NULL) fCodons= (CodonStat*) MemNew( 64 * sizeof(CodonStat));
  396. }
  397.  
  398. const char* DCodons::FindBestCodon( char matchamino)
  399. {
  400.     //shorten this x64 loop w/ sorted CodonTable sorted by most freq form/aa 
  401.     short k, bestk= -1;
  402.     float bestNumPerK= 0;
  403.     Boolean nomatch;
  404.     
  405.     for (k= 0, nomatch= true; k<64 && nomatch; k++) {
  406.         if (fCodons[k].amino == matchamino) {
  407.              if (bestk<0 || fCodons[k].numPerK > bestNumPerK) {
  408.                 bestk= k;
  409.                 bestNumPerK= fCodons[k].numPerK;
  410.                 }
  411.             }
  412.         else if (fCodons[k].amino > matchamino) {
  413.             nomatch= false;
  414.             }
  415.         }
  416.     if (bestk<0) return "NNN";  
  417.     else return fCodons[bestk].codon;
  418. }
  419.  
  420.  
  421.  
  422. void DCodons::TableChoice()
  423. {
  424.     char* title= "Codon Table";
  425.     char* desc = 
  426. "  gcg style, '..' signals start of data"LINEEND
  427. "AmAcid  Codon     Number    /1000     Fraction   .."LINEEND
  428. "Gly     GGG     1743.00      9.38      0.13"LINEEND
  429. "Gly     GGA     1290.00      6.94      0.09"LINEEND
  430. ;
  431.     char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  432.     
  433.     DTableChoiceDialog* win= new DTableChoiceDialog(title, desc, tablefile);
  434.     if (win->PoseModally()) {
  435.         ReadTable( win->fFile);
  436.         if (fState != kOkay) {
  437.             Message(MSG_OK, "Table wasn't properly loaded.  Please try again");
  438.             }
  439.         else if (win->fSetPref)
  440.             gApplication->SetPref((char*)win->fFile->GetName(), fType, fSection);
  441.         }
  442.     MemFree( tablefile);
  443.     delete win;
  444. }
  445.  
  446.  
  447. void DCodons::ReadTable( char* tableFile)
  448. {
  449.      DFile aFile( tableFile, "r");
  450.     ReadTable( &aFile);
  451.     //delete aFile;
  452. }
  453.  
  454. #ifdef WIN_MSWIN
  455. static int LIBCALLBACK
  456. #else
  457. static int
  458. #endif
  459. aminosort(void* a, void* b)
  460. {
  461.     return ( ((CodonStat*)a)->amino -  ((CodonStat*)b)->amino);
  462. }
  463.  
  464. void DCodons::ReadTable(DFile* aFile)
  465. {
  466. /*------ file format for codon table (gcg style)
  467. AmAcid  Codon     Number    /1000     Fraction   ..
  468.          1         2         3         4   
  469. 12345678901234567890123456789012345678901234567890
  470. Gly     GGG     1743.00      9.38      0.13
  471. Gly     GGA     1290.00      6.94      0.09
  472. ------*/
  473.     const    short kLinemax= 512;
  474.      Boolean done= FALSE;
  475.     char        amino3[5], codon[5], startc;
  476.     char        line[kLinemax];
  477.     short        na;
  478.     float        number, numPerK, frac;
  479.     
  480.     //fState= kNodata;
  481.     if (!aFile || !aFile->Exists()) return;
  482.     aFile->OpenFile();
  483.     do {
  484.         aFile->ReadLine( line, kLinemax);
  485.         done= (StrStr(line,"..") != NULL);
  486.     } while (!done && !aFile->Eof());
  487.     
  488.     done= FALSE;
  489.     startc= 0;
  490.     na= 0; 
  491.     while (!done && !aFile->Eof()) {
  492.         number= -1;
  493.         aFile->ReadLine( line, kLinemax); // eat line
  494.         if (*line > ' ') {
  495.             sscanf( line, "%3s %3s %f %f %f", &amino3, &codon, &number, &numPerK, &frac);
  496.             }
  497.         if (number > 0) {
  498.                     // use GCG practice of signifying start codon w/ all lowercase
  499.             fCodons[na].amino= DSequence::Amino321( amino3);
  500.           if (islower(amino3[0]) && islower(amino3[1]) && islower(amino3[2])) 
  501.                 startc= fCodons[na].amino;
  502.             codon[0]= toupper(codon[0]);
  503.             codon[1]= toupper(codon[1]);
  504.             codon[2]= toupper(codon[2]);
  505.             StrNCpy( fCodons[na].codon,codon,4);
  506.             fCodons[na].numPerK= numPerK;
  507.             na++;
  508.             }
  509.         done= na>= 64;
  510.         }
  511.     
  512.     if (done) {
  513.         Nlm_HeapSort(fCodons, 64, sizeof(CodonStat), aminosort);
  514.         if (!startc) startc= 'M'; // Met is usual start codon
  515.         for (short i= 0; i<64; i++) 
  516.           if (fCodons[i].amino == startc) { fStartcodon= i; break; }
  517.         fState= kOkay;
  518.         }
  519.     else fState= kNodata;
  520. }
  521.  
  522.  
  523.  
  524.  
  525.  
  526. // class DREnzyme
  527.  
  528.  
  529. DREnzyme::DREnzyme()
  530. {
  531.     fName= NULL;
  532.     fSite= NULL;
  533.     fCoSite= NULL;
  534.     fVendors= NULL;
  535.     fCutpoint = -1;
  536.     fCoCutpoint= -1;
  537.     fCut3from5 = 0;
  538.     fCutcount= 0;
  539. }
  540.  
  541. DREnzyme::~DREnzyme()
  542. {
  543.     MemFree( fName);
  544.     MemFree( fSite);
  545.     MemFree( fCoSite);
  546.     MemFree( fVendors);
  547. }
  548.  
  549.     
  550. Boolean DREnzyme::Parse( char* line)
  551. /*----
  552. [Name            Cut  Site                    ? !   Isoschizomers?                    >vendors ]
  553. ;AatI      3 AGG'CCT        0 !  Eco147I,StuI                 >OU
  554. AatII      5 G_ACGT'C      -4 !               >EGJLMNOPRSUVX
  555. AccI       2 GT'mk_AC       2 !               >ABDEGIJKLMNOPQRSUVXY
  556. ;AccII     2 CG'CG          0 !  Bsp50I,BstUI,MvnI,ThaI      >DEGJKQVXY
  557.  
  558. ? skip lines starting w/ ;
  559. ----*/
  560. {
  561.     //assume caller has eliminated blank lines 
  562.     short        i, k, l, len, sitel;
  563.     char        sitebuf[kMaxSite];
  564.     
  565.     if (*line == ';')  return false;
  566.     fCutpoint= 0;
  567.     fCut3from5= 0;
  568.  
  569.     i= 0; 
  570.     len= StrLen(line);
  571.     while (i<len && line[i]<=' ') i++;
  572.     k= i;
  573.     while (i<len && line[i]>' ') i++;
  574.     l= i-k;
  575.     fName= (char*) MemNew(l+1);
  576.     StrNCpy( fName, line+k, l); 
  577.     fName[l]= 0;
  578.     
  579.         //get cutpoint ?
  580.     while (i<len && line[i]<=' ') i++;
  581.     k= i;
  582.     while (i<len && line[i]>' ') i++;
  583.     l= i-k;
  584.     // word= copy(line,k,l); StringToNumber(word, long); fCutpoint= long; 
  585.     fCutpoint= atol(line+k);
  586.     
  587.         // get site && cutpoint 
  588.     while (i<len && line[i]<=' ') i++;    
  589.     k= i;
  590.     for (l= 0; i<len && line[i]>' ' && l<kMaxSite; i++) {
  591.         if (isalpha(line[i])) sitebuf[l++]= line[i];
  592.         }
  593.     sitel= l;
  594.     sitebuf[sitel]= 0;
  595.     fSite= (char*) MemNew(sitel+1);
  596.     MemCpy(fSite, sitebuf, sitel+1);
  597.     
  598.         //skip fCut3from5 value ?
  599.     while (i<len && line[i]<=' ') i++;
  600.     k= i;
  601.     while (i<len && line[i]>' ') i++;
  602.     //l= i-k;
  603.     fCut3from5= atol(line+k);
  604.  
  605.     //Boolean unsym= (fCut3from5 != 0 || sitel & 1);
  606.     if (1) {
  607. #if 1
  608.         long i;
  609.         char* aCoSite= (char*) MemNew(sitel+1);  
  610.         for (i=0; i<sitel; i++) aCoSite[sitel-i-1]= fSite[i];
  611.         aCoSite[sitel]= 0;
  612.             // ?? do complement before or after strcmp ?? likewise, reverse when?
  613.         DSequence::NucleicComplement( false, aCoSite, aCoSite, sitel);
  614.         if ( StringCmp(aCoSite, fSite) != 0) fCoSite= aCoSite;
  615.         else MemFree(aCoSite); 
  616. #else
  617.         long i, j;
  618.         char* aCoSite= (char*) MemNew(sitel+1);  
  619.         for ( i=0; i<sitel; i++) aCoSite[i]= fSite[i];
  620.         aCoSite[sitel]= 0;
  621.             // ?? do complement before or after strcmp ?? likewise, reverse when?
  622.         DSequence::NucleicComplement( false, aCoSite, aCoSite, sitel);
  623.         if ( StringCmp(aCoSite, fSite) != 0) {
  624.             for (i=0, j= sitel-1; i<j; i++, j--) {
  625.                 char c= aCoSite[i];
  626.                 aCoSite[i]= aCoSite[j];
  627.                 aCoSite[j]= c;
  628.                 }
  629.             aCoSite[sitel]= 0; // be sure ...
  630.             fCoSite= aCoSite;
  631.             }
  632.         else MemFree(aCoSite); 
  633. #endif
  634.  
  635. #if 1
  636.         fCoCutpoint= sitel - (fCutpoint + fCut3from5); 
  637. #else
  638.         if (fCut3from5) fCoCutpoint= sitel - (fCutpoint + fCut3from5); 
  639.         else fCoCutpoint= fCutpoint; // ?????? 
  640. #endif
  641.         }
  642.     
  643.     
  644.         //skip past "!"
  645.     while (i<len && line[i] != '!') i++;    
  646.     i++;
  647.         
  648.         //get Isoschizomers? -- not all have them! ?
  649.     while (i<len && line[i]<=' ') i++;
  650.     if (line[i] != '>') {
  651.         k= i;
  652.         while (i<len && line[i]>' ') i++;
  653.         l= i-k;
  654.             //skip past ">"
  655.         while (i<len && line[i] != '>') i++;
  656.         }
  657.     i++;
  658.     
  659.         //get vendors  
  660.     while (i<len && line[i]<=' ') i++;
  661.     k= i;
  662.     while (i<len && line[i]>' ') i++;
  663.     l= i-k; //Min(63,i-k);
  664.     fVendors= (char*) MemNew(l+1);
  665.     StrNCpy( fVendors, line+k, l); 
  666.     fVendors[l]= 0;
  667.     
  668.     return true;
  669. }
  670.         
  671.  
  672.  
  673. // class DREnzymeVendor
  674.  
  675.  
  676. DREnzymeVendor::DREnzymeVendor()
  677. {
  678.     fCode = '!';
  679.     fName    = NULL;
  680. }
  681.  
  682. DREnzymeVendor::~DREnzymeVendor()
  683. {
  684.     if (fName) MemFree( fName);
  685. }
  686.  
  687. Boolean DREnzymeVendor::Parse( char* line)
  688. // e.g.,  "A    Amersham (4/91)" 
  689. {
  690.     //assume caller has eliminated blank lines & flushed blanks from front & back 
  691. #if 1
  692.     char *cp= line;
  693.     fCode= *line;
  694.     line++;
  695.     while (*line && *line<=' ') line++;
  696.     fName= StrDup( line);
  697. #else
  698.     short        i, j, k, l, len;
  699.     len= StrLen(line);
  700.     for (i=0; i<len && line[i]<=' '; i++) ;
  701.     fCode= line[i];
  702.     i++;
  703.     while (i<len && line[i]<=' ') i++;
  704.     l= len-i;
  705.     fName= (char*) MemNew(l+1);
  706.     StrNCpy( fName, line+i, l); 
  707.     fName[l]= 0;
  708. #endif
  709.  
  710.     return true;
  711. }
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721. // DREMap ---------------------------------
  722.         
  723.  
  724. short DREMap::fState= DREMap::kUnread;
  725. char* DREMap::fType= "renzyme";
  726. char* DREMap::fSection= "data";
  727. char* DREMap::fDefaultvalue= "tables:renzyme.table";
  728. DList    * DREMap::fREnzymes = NULL ;                // of DREnzyme ?? same as gREnzymes
  729. DList    * DREMap::fREnzymeVendors = NULL ;     // of DREnzymeVendor
  730.     
  731.     
  732. //static
  733. void DREMap::Initialize(char* type, char* section, char* defaultvalue)
  734. {
  735.     fREnzymes= NULL; //?
  736.     fREnzymeVendors= NULL; //?
  737.     fState= kUnread;
  738.     fType= type;
  739.     fSection= section;
  740.     fDefaultvalue= defaultvalue;
  741. }
  742.  
  743.  
  744.  
  745. DREMap::DREMap()
  746. {
  747.     fSeq= NULL;
  748.     fCoSeq= NULL;
  749.     fSeqCuts= NULL;
  750.     fCutcount= 0;
  751.     fCuttersCount= 0;
  752.     fType= "renzyme";
  753.     fSection= "data";
  754.     fDefaultvalue= "tables:renzyme.table";
  755. }
  756.  
  757. DREMap::~DREMap()  
  758. {
  759.     FreeTempData();
  760.     //FreeEnzymeList(); 
  761. }
  762.  
  763.  
  764.  
  765. //static
  766. void DREMap::FreeEnzymeList()
  767. {
  768.     fREnzymes = FreeListIfObject(fREnzymes); 
  769.     fREnzymeVendors = FreeListIfObject(fREnzymeVendors); 
  770. }
  771.  
  772. void DREMap::FreeTempData() 
  773. {
  774.     fSeq= NULL;
  775.     delete fCoSeq; fCoSeq= NULL;
  776.     MemFree(fSeqCuts); fSeqCuts= NULL;
  777.     fCutcount= 0;
  778.     fCuttersCount= 0;
  779. }
  780.  
  781. //static
  782. Nlm_Boolean DREMap::NotAvailable()
  783. {
  784.     if (fState == kUnread) {
  785.         char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  786.         if (tablefile) {
  787.           ReadTable( tablefile);
  788.             if (fState != kOkay) {
  789.                 // dialog - would you like to locate data?
  790.                 DLocateFile* win= new DLocateFile("Could not read table file '%s'", tablefile);
  791.                 if (win->PoseModally()) {
  792.                     ReadTable( win->fName);
  793.                     if (fState == kOkay)
  794.                         gApplication->SetPref( win->fName, fType, fSection); //??
  795.                     }
  796.                 delete win;
  797.                 }
  798.             }
  799.         else fState= kNodata;
  800.         if (fState != kOkay) Message(MSG_OK,"Could not read table file '%s'",tablefile);
  801.         MemFree( tablefile);
  802.         }
  803.     return (fState != kOkay);
  804. }
  805.  
  806. //static
  807. void DREMap::TableChoice()
  808. {
  809.     char* title= "R.Enzyme Table";
  810.     char* desc = 
  811. "    gcg format, '..' signals start of data"LINEEND
  812. "REBASE abbreviations for commercial sources of restriction enzymes"LINEEND
  813. "                A        Amersham (5/93)"LINEEND
  814. "                Y        P.C. Bio (9/91)"LINEEND
  815. "[Name            Cut  Site         Cut3-5 !   Isoschizomers?     >vendors]"LINEEND
  816. ".."LINEEND
  817. ";AatI      3 AGG'CCT        0 !  Eco147I,StuI         >OU"LINEEND
  818. "AatII      5 G_ACGT'C      -4 !                       >ELMNOPRSUX"LINEEND
  819. "AccI       2 GT'mk_AC       2 !                       >ABDEGKLMNOPQRSUX"LINEEND
  820. ";AccII     2 CG'CG          0 !  BstUI,MvnI,ThaI,Bsh1236I  >KQX"LINEEND
  821. ;
  822.     char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  823.  
  824.     DTableChoiceDialog* win= new DTableChoiceDialog(title, desc, tablefile);
  825.     if (win->PoseModally()) {
  826.         ReadTable( win->fFile);
  827.         if (fState != kOkay) {
  828.             Message(MSG_OK, "REnzyme table wasn't properly loaded.  Please try again");
  829.             }
  830.         else if (win->fSetPref)
  831.             gApplication->SetPref((char*)win->fFile->GetName(), fType, fSection);
  832.         }
  833.     MemFree( tablefile);
  834.     delete win;
  835. }
  836.  
  837. //static
  838. void DREMap::ReadTable( char* tableFile)
  839. {
  840.      DFile aFile( tableFile, "r");
  841.     ReadTable( &aFile);
  842.     //delete aFile;
  843. }
  844.  
  845. //static
  846. void DREMap::ReadTable(DFile* aFile)  
  847. /*------ file format for Restriction Enzyme table (REbase in wisconsin/GCG format)
  848. blah, blah
  849.  
  850. Commercial sources of restriction enzymes are abbreviated as follows:
  851.  
  852.         A    Amersham (4/91)
  853.         :        :
  854.          Y    P.C. Bio (9/91)
  855.  
  856. [Name            Cut  Site         Cut3-5 !   Isoschizomers?                    >vendors \newline]
  857. ..
  858. ;AatI      3 AGG'CCT        0 !  Eco147I,StuI                      >OU
  859. AatII      5 G_ACGT'C      -4 !         >EGJLMNOPRSUVX
  860. AccI       2 GT'mk_AC       2 !         >ABDEGIJKLMNOPQRSUVXY
  861. ;AccII     2 CG'CG          0 !  Bsp50I,BstUI,MvnI,ThaI            >DEGJKQVXY
  862.     :                        :
  863. ----------------*/
  864. {
  865.     const    short kLinemax = 512;
  866.     char                line[kLinemax+1];
  867.     Boolean         done, gotfirst;
  868.     char    * cp;
  869.  
  870.     //fState= kNodata;
  871.      if (!aFile || !aFile->Exists()) return;
  872.      
  873.     FreeEnzymeList();
  874.     fREnzymeVendors = new DList(); // of StringHandle 
  875.     fREnzymes    = new DList();    // of REnzymeHandle 
  876.  
  877.     aFile->OpenFile();
  878.     done= FALSE;            
  879.     gotfirst= FALSE;
  880.     while (!done && !aFile->Eof()) {
  881.         aFile->ReadLine( line, kLinemax);
  882.         done= StrStr(line, "sources of restriction enzymes") != NULL;
  883.         if (!done) {
  884.             gotfirst= TRUE;
  885.             done= StrStr(line, "Amersham") != NULL;  //vendor, maybe key line was changed...
  886.             }
  887.         }
  888.  
  889.         // Read vendor codes 
  890.     for (done= false; !done && !aFile->Eof(); ) {
  891.         if (!gotfirst) aFile->ReadLine( line, kLinemax);
  892.         gotfirst= false;
  893.         cp= FlushLine(line);
  894.         if (*cp) {
  895.             DREnzymeVendor* rev = new DREnzymeVendor();
  896.             if (rev->Parse( cp))
  897.                 fREnzymeVendors->InsertLast( rev);
  898.             else
  899.                 delete rev;
  900.             }
  901.         done= (StrStr(cp, "..") != NULL);  // GCG format data separator 
  902.         }
  903.     
  904.         // Read Enzymes 
  905.     for (done= false; !done && !aFile->Eof(); ) {
  906.         aFile->ReadLine( line, kLinemax);
  907.         cp= FlushLine( line);
  908.         if (*cp) {
  909.             DREnzyme*    re = new DREnzyme();
  910.             if (re->Parse( cp))
  911.                 fREnzymes->InsertLast( re);
  912.             else
  913.                 delete re;
  914.             }
  915.         }
  916.         
  917.     done= true; // !! need some test of acurrate read !!
  918.     if (done) {
  919.         fState= kOkay;
  920.         }
  921.     else fState= kNodata;
  922. }
  923.  
  924.  
  925. void DREMap::HuntCut( short n, short x, short& jlo)
  926. {    
  927.     short        jm, jhi, inc;
  928.     Boolean        done;
  929.  
  930.     jlo= 0; //TESTING....
  931.     
  932.     //- ascend= ((*fSeqCuts)^[n].fSeqIndex > (*fSeqCuts)^[1].fSeqIndex); 
  933.     if (jlo <= 0 || jlo > n) {
  934.         jlo= 0; 
  935.         jhi= n+1;
  936.         }
  937.         
  938.     else { // hunt from last low value section 
  939.         inc= 1;
  940.         if ( x >= fSeqCuts[jlo].fSeqIndex ) // ascend
  941.             do {
  942.                 jhi= jlo + inc;
  943.                 done= TRUE; 
  944.                 if (jhi > n)  
  945.                     jhi= n+1;
  946.                 else if ( x >= fSeqCuts[jhi].fSeqIndex ) {
  947.                     jlo= jhi; inc= inc + inc;
  948.                     done= FALSE; 
  949.                     }
  950.             } while (!done);
  951.             
  952.         else {
  953.             jhi= jlo;
  954.             do {
  955.                 jlo= jhi - inc;
  956.                 done= TRUE; 
  957.                 if (jlo < 1)
  958.                     jlo= 0;
  959.                 else if ( x < fSeqCuts[jlo].fSeqIndex) { //== ascend
  960.                     jhi= jlo; inc= inc + inc;
  961.                     done= FALSE;
  962.                     }
  963.             } while (!done);
  964.             }
  965.         }
  966.             // bisection 
  967.     while (jhi - jlo > 1) {
  968.         jm= (jhi + jlo) / 2;
  969.         if ( x > fSeqCuts[jm].fSeqIndex ) jlo= jm;
  970.         else if ( x == fSeqCuts[jm].fSeqIndex ) { jlo= jm; return; }
  971.         else jhi= jm;
  972.         }
  973. }        
  974.  
  975.  
  976. void DREMap::CutsAtBase( short atBase, short& firstCut, short& nCuts)
  977. {
  978.     short icut;
  979.         
  980.     nCuts= 0;
  981.     if ( fSeqCuts && fCutcount>0 ) {
  982.         /*-----
  983.         while ( ((*fSeqCuts)^[icut].fSeqIndex < atBase) do icut= icut+1;  
  984.         firstCut= icut;
  985.         ------*/
  986.         HuntCut( fCutcount, atBase, firstCut);    
  987.             //hunt may find middle of a run
  988.         while ( firstCut>1 && fSeqCuts[firstCut-1].fSeqIndex == atBase )
  989.             firstCut--;
  990.         icut= firstCut;  
  991.         while (fSeqCuts[icut].fSeqIndex == atBase) {
  992.             nCuts++;
  993.             icut++;
  994.             }
  995.         }
  996.     if (nCuts == 0) firstCut= 0; //??
  997. }
  998.  
  999.  
  1000.  
  1001. enum {     kSearchNotFound = -1, kStep = 1 };
  1002.  
  1003. long DREMap::QuickSearch( Nlm_Boolean first, char* target, long targlen, 
  1004.                             char* source, long sourcelen)
  1005. {
  1006.     static long qIndex;
  1007.     register char tBase; // fTargetbase
  1008.     
  1009.     tBase = target[0];
  1010.     if (first) {
  1011.         qIndex= -kStep;   
  1012.         if (!tBase) return kSearchNotFound;
  1013.         }
  1014.  
  1015. lNextStep:
  1016.     qIndex += kStep; 
  1017.     for (register long j= qIndex; j<sourcelen; j++) {  
  1018.         if (tBase & source[j]) {
  1019.             qIndex = j; 
  1020.                         //? enough source left to match full target 
  1021.             if (sourcelen-qIndex < targlen) 
  1022.                 return kSearchNotFound;
  1023.             else {
  1024.               register char * sp = source + qIndex + 1;
  1025.               register char * tp = target + 1;
  1026.               register long k = targlen-1;
  1027.               long k1= sourcelen - qIndex - 1;
  1028.               if (k1<k) k= k1;
  1029.               if (k<1) goto lNextStep;
  1030.               for ( ; (k); k--) 
  1031.                   if ((*sp++ & *tp++) == 0) goto lNextStep; // no match
  1032.                   
  1033.               if (source[qIndex] == DSequence::kMaskNucs) {
  1034.                       // screen out all N's here -- don't want to match these !?
  1035.                   sp = source + qIndex + 1;
  1036.                   for (k= targlen-1; (k); k--) 
  1037.                       if (*sp++ != DSequence::kMaskNucs) return qIndex;  // non-NNN match
  1038.                   goto lNextStep; // got all Ns .. continue scan
  1039.                   }
  1040.               else
  1041.                     return qIndex; // matched
  1042.                 }
  1043.             }
  1044.         }
  1045.     return kSearchNotFound;
  1046.  
  1047.     
  1048.  
  1049. void DREMap::SearchStrand( DSequence* bSeq, char* aTarget, char* sourcebits, long sourcelen,
  1050.                                             DREnzyme* zyme, short cutAdd, long& zymecuts)
  1051. {
  1052.     long  targlen, i, len;
  1053.   char   tb, * targbits;
  1054.   
  1055.   len= StrLen(aTarget);
  1056.   targbits= (char*) MemNew(len+1);
  1057.     for ( i=0, targlen = 0; i<len; i++) { 
  1058.         tb = (char) DSequence::kMaskNucs & DSequence::NucleicBits(aTarget[i]);
  1059.         if (tb) targbits[targlen++]= tb;
  1060.         }
  1061.   targbits[targlen]= 0;
  1062.   
  1063.     long indx= QuickSearch( true, targbits, targlen, sourcebits, sourcelen);
  1064.     while (indx != kSearchNotFound) {
  1065.         if (fCutcount >= fMaxcuts) {
  1066.             fMaxcuts += 100;
  1067.             fSeqCuts= (DRECutsItem*) MemMore( fSeqCuts, fMaxcuts * sizeof(DRECutsItem));
  1068.             }
  1069.         fSeqCuts[fCutcount].fSeqIndex= indx + cutAdd;
  1070.         fSeqCuts[fCutcount].fREnzyme= zyme;
  1071.         fCutcount++;
  1072.         zymecuts++;
  1073.         indx= QuickSearch( false, targbits, targlen, sourcebits, sourcelen);
  1074.         }
  1075.     MemFree(targbits);
  1076. }
  1077.         
  1078.  
  1079. void DREMap::FindCuts( DREnzyme* zyme, char* sourcebits, long sourcelen)
  1080. {
  1081.      long    zymecuts;
  1082.  
  1083.     zymecuts= 0;
  1084.     SearchStrand( fSeq, zyme->fSite, sourcebits, sourcelen, zyme, zyme->fCutpoint, zymecuts);
  1085.  
  1086.     if (zyme->fCoSite) {
  1087.         // only do when 3' differs from 5' 
  1088.         //!? ignore symmetric sites -- are these symmetric if fCut3!=fCut5
  1089.         //!? also need to screen sites that are symmetric about cut points !?
  1090.  
  1091.         SearchStrand( fSeq, zyme->fCoSite, sourcebits, sourcelen, zyme, 
  1092.                                     zyme->fCoCutpoint, zymecuts);
  1093.         }
  1094.     zyme->fCutcount= zymecuts;
  1095.     if (zymecuts>0) fCuttersCount++;
  1096. }
  1097.  
  1098.  
  1099. #ifdef WIN_MSWIN
  1100. static int LIBCALLBACK
  1101. #else
  1102. static int
  1103. #endif
  1104.  
  1105. cutterCompare(void* a, void* b)
  1106. {
  1107.     short diff= ((DRECutsItem*)a)->fSeqIndex - ((DRECutsItem*)b)->fSeqIndex;
  1108.     if (diff == 0) {
  1109.         return StringCmp(((DRECutsItem*)a)->fREnzyme->fName, 
  1110.                                   ((DRECutsItem*)b)->fREnzyme->fName);
  1111.         }
  1112.     else
  1113.         return diff;
  1114. }
  1115.  
  1116.  
  1117. void DREMap::MapSeq( DSequence* aSeq)
  1118. {
  1119.     long  i, nzymes, len, sourcelen, aStart, aBases;
  1120.     char * sourcebits, sb;
  1121.     
  1122.     FreeTempData();
  1123.     if (NotAvailable()) return;
  1124.     fSeq= aSeq;
  1125.     fSeq->GetSelection( aStart, aBases);
  1126.     
  1127.         
  1128. #if 1
  1129.     fCoSeq= aSeq->Complement();
  1130. #else
  1131.     aSeq->SetSelection(0,0); // for Complement...
  1132.     fCoSeq= aSeq->Complement();
  1133.     aSeq->SetSelection(aStart,aBases);  
  1134. #endif
  1135.     
  1136.     // make a NucBits form of fBases, once  
  1137. #if 0
  1138.         // this needs work -- draw currently expects start of seq/remap == 0, not aStart
  1139.     if (aBases) {
  1140.         len= aBases;
  1141.         sourcebits= (char*) MemNew(len+1);
  1142.         StrNCpy( sourcebits, aStart+fSeq->Bases(), len);
  1143.         sourcebits[len]= 0;
  1144.         }
  1145.     else
  1146. #endif
  1147.     {
  1148.     sourcebits= StrDup( fSeq->Bases());
  1149.     len= StrLen(sourcebits);
  1150.     }
  1151.     for (i= 0, sourcelen= 0; i<len; i++) {
  1152.         sb = (char) DSequence::kMaskNucs & DSequence::NucleicBits(sourcebits[i]);
  1153.         if (sb) sourcebits[sourcelen++]= sb;
  1154.         }
  1155.       // drop trailing "..." Ns
  1156.     while (sourcelen && sourcebits[sourcelen-1] == DSequence::kMaskNucs) 
  1157.         sourcelen--;
  1158.   sourcebits[sourcelen]= 0;
  1159.         
  1160.     fCutcount= 0; 
  1161.     fMaxcuts = 0;
  1162.     fSeqCuts= (DRECutsItem*) MemNew(sizeof(DRECutsItem));
  1163.     nzymes= fREnzymes->GetSize();
  1164.     for (i=0; i<nzymes; i++) {
  1165.         DREnzyme* re= (DREnzyme*) fREnzymes->At(i);
  1166.         FindCuts( re, sourcebits, sourcelen);
  1167.         }
  1168.     MemFree( sourcebits);
  1169.   
  1170.     Nlm_HeapSort( fSeqCuts, fCutcount, sizeof(DRECutsItem), cutterCompare);
  1171.     
  1172.         // !! check for ident. zyme cuts at same site ?!!!
  1173.   short at, lastat= -1;
  1174.   char *name, *lastname=NULL;
  1175.   for (i=0; i<fCutcount; i++) {
  1176.       at= fSeqCuts[i].fSeqIndex;
  1177.       name= fSeqCuts[i].fREnzyme->fName;
  1178.       if (lastat == at && StringCmp(name, lastname)==0)
  1179.         fSeqCuts[i].fREnzyme->fCutcount--;
  1180.       lastname= name;
  1181.       lastat= at;
  1182.       }
  1183. }
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191. // class DBaseColors
  1192.  
  1193. short DBaseColors::fState= DBaseColors::kUnread;
  1194. char* DBaseColors::fType= "color";
  1195. char* DBaseColors::fSection= "data";
  1196. char* DBaseColors::fDefaultvalue= "tables:color.table";
  1197. baseColors DBaseColors::gAAcolors;
  1198. baseColors DBaseColors::gNAcolors;
  1199.     
  1200. typedef unsigned long  colorVal;
  1201.  
  1202. Local colorVal        kBlack     = 0; 
  1203. Local colorVal        kRed         = (255<<16);
  1204. Local colorVal        kGreen     = (255<<8);
  1205. Local colorVal        kBlue     = (255<<0);
  1206. Local colorVal        kWhite     = 0xffffff00;
  1207. Local colorVal         kYellow = (255<<16) | (255<<8);
  1208. Local colorVal         kMagenta= (255<<16) | (255<<0);
  1209. Local colorVal         kCyan     = (255<<8) | (255<<0);
  1210. Local colorVal         kOrange = (255<<16) | (110<<8); // | 15<<0;
  1211. Local colorVal         kOrange1 = (200<<16) | (110<<8); // | 15<<0; // this is brownish orange
  1212. Local colorVal         kGreen1    = (200<<8) | (31<<16) | (21<<0);
  1213. Local colorVal        kGray     = (127<<8) | (127<<16) | (127<<0);
  1214. Local colorVal        kLtGray = (191<<8) | (191<<16) | (191<<0);
  1215. Local colorVal        kDkGray = (63<<8) | (63<<16) | (63<<0);
  1216.  
  1217.  
  1218. Nlm_Boolean DBaseColors::NotAvailable()
  1219. {
  1220.     if (fState == kUnread) {
  1221.         char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  1222.         if (tablefile) {
  1223.             ReadTable( tablefile);
  1224.             if (fState != kOkay) {
  1225.                 DLocateFile* win= new DLocateFile("Could not read table file '%s'", tablefile);
  1226.                 if (win->PoseModally()) {
  1227.                     ReadTable( win->fName);
  1228.                     if (fState == kOkay)
  1229.                         gApplication->SetPref( win->fName, fType, fSection); //??
  1230.                     }
  1231.                 delete win;
  1232.                 }
  1233.             }
  1234.         else fState= kNodata;
  1235.         if (fState != kOkay) Message(MSG_OK,"Could not read table file '%s'",tablefile);
  1236.         MemFree( tablefile);
  1237.         }
  1238.     return (fState != kOkay);
  1239. }
  1240.  
  1241. void DBaseColors::Initialize(char* type, char* section, char* defaultvalue)
  1242. {
  1243.     fState= kUnread;
  1244.     fType= type;
  1245.     fSection= section;
  1246.     fDefaultvalue= defaultvalue;
  1247.     InitColors();
  1248. }
  1249.  
  1250. // static
  1251. void DBaseColors::TableChoice()
  1252. {
  1253.     char * title = "Base Color Table";
  1254.     char* desc = 
  1255. "[nacolors]"LINEEND
  1256. "; nucleic acid colors"LINEEND
  1257. "; base=color value ;add line for each base desired in set [' '..'~']"LINEEND
  1258. "; put two color values on a line for UPPER and lowercase bases"LINEEND
  1259. "A=0xffaa88"LINEEND
  1260. "C=0xaaff88"LINEEND
  1261. "G=0x8877ff"LINEEND
  1262. "T=0x88aaaa"LINEEND
  1263. "[aacolors]"LINEEND
  1264. "; amino acid colors"LINEEND
  1265. "A=0xaaff88"LINEEND
  1266. "B=0xffaa88"LINEEND
  1267. "; ... etc ..."LINEEND
  1268.  
  1269.     char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  1270.     DTableChoiceDialog* win= new DTableChoiceDialog(title,desc,tablefile);
  1271.     if (win->PoseModally()) {
  1272.         ReadTable( win->fFile);
  1273.         if (fState != kOkay) {
  1274.             Message(MSG_OK, "Table wasn't properly loaded.  Please try again");
  1275.             }
  1276.         else if (win->fSetPref)
  1277.             gApplication->SetPref((char*)win->fFile->GetName(), fType, fSection);
  1278.         }
  1279.     MemFree( tablefile);
  1280.     delete win;
  1281. }
  1282.  
  1283.  
  1284.  
  1285. static void ReadColors( char* colorstr, colorVal& ncolor1, colorVal& ncolor2, Boolean& twocolors)
  1286. {
  1287.         // this is failing to get correct color !!
  1288.         // sometimes no where near correct (grey -> black or white)
  1289.         // colorstr is read correctly into color1/color2
  1290.         // but SelectColor/GetColor pair loses it...
  1291.         
  1292.     unsigned short cr, cg, cb;
  1293.     //Nlm_Uint1  cr, cg, cb;
  1294.   unsigned long color1 = 0, color2 = 0;
  1295.     char * ep;
  1296.  
  1297.     ep= StrChr(colorstr,';'); if (ep) *ep= 0;
  1298.     colorstr= FlushLine( colorstr);
  1299.     twocolors= (StrChr(colorstr,' ') != NULL);
  1300.          // this works on Sol2, but %lx doesn't !
  1301.   sscanf( colorstr, "%li %li", &color1, &color2);  
  1302.   
  1303.     cr= (color1>>16) & 0xff;
  1304.     cg= (color1>>8) & 0xff;
  1305.     cb= (color1) & 0xff;
  1306. #ifdef WIN_MAC
  1307.     // color1 is correct format
  1308. #endif
  1309. #ifdef WIN_MSWIN
  1310.   color1 = (cr | cg << 8 | ((ulong)cb) << 16); //RGB (cr, cg, cb);
  1311. #endif
  1312. #ifdef WIN_MOTIF
  1313.     // X uses mapped values thru setcolor -- need to do the select/get dance
  1314.     Nlm_SelectColor( cr, cg, cb);
  1315.     color1= Nlm_GetColor();
  1316. #endif
  1317.     ncolor1= color1;
  1318.  
  1319.     if (twocolors) {
  1320.         cr= (color2>>16) & 0xff;
  1321.         cg= (color2>>8) & 0xff;
  1322.         cb= (color2) & 0xff;
  1323. #ifdef WIN_MAC
  1324.     // color2 is correct format
  1325. #endif
  1326. #ifdef WIN_MSWIN
  1327.   color2 = (cr | cg << 8 | ((ulong)cb) << 16); //RGB (cr, cg, cb);
  1328. #endif
  1329. #ifdef WIN_MOTIF
  1330.     // X uses mapped values thru setcolor -- need to do the select/get dance
  1331.         Nlm_SelectColor( cr, cg, cb);
  1332.         color2= Nlm_GetColor();
  1333. #endif
  1334.         ncolor2= color2;
  1335.         }
  1336. }
  1337.  
  1338.  
  1339. void DBaseColors::ReadTable( char* tableFile)
  1340. {
  1341.      DFile aFile( tableFile, "r");
  1342.     ReadTable( &aFile);
  1343. }
  1344.  
  1345.  
  1346. void DBaseColors::ReadTable(DFile* aFile)
  1347. {
  1348.     Boolean done= false;
  1349.     unsigned long*    curcolors;
  1350.     short      iline, nlines = 0;
  1351.     char    * line;
  1352.      char**    linelist;
  1353.  
  1354.     //fState= kNodata;
  1355.     if (!aFile || !aFile->Exists()) return;
  1356.     colorVal savecolor= Nlm_GetColor();    
  1357.     
  1358.     aFile->Open("r");
  1359.      linelist= Dgg_ReadDefaultPrefs( aFile->fFile, &nlines);
  1360.     
  1361.     for (iline= 0; iline<nlines; iline++) {
  1362.         line= linelist[iline];
  1363.         if (line && *line) {
  1364.             if (*line == '[') { // sect name 
  1365.                 if (StrNICmp(line+1,"nacolor",7)==0)  
  1366.                     curcolors= &gNAcolors[0];
  1367.                 else if (StrNICmp(line+1,"aacolor",7)==0) 
  1368.                     curcolors= &gAAcolors[0];
  1369.                 else 
  1370.                     curcolors= NULL;
  1371.                 }
  1372.             else if (*line == ';') {
  1373.                 // skip comment
  1374.                 }
  1375.             else if (curcolors) {
  1376.                 char* colorval= StrChr(line, '=');
  1377.                 if (colorval) {
  1378.                         // look for 2 values in color value, up & lowcase char colors !?
  1379.                     Boolean     twocolors= false;
  1380.                     colorVal    ncolor1, ncolor2;
  1381.                     char basec= *line;
  1382.                     ::ReadColors( colorval+1, ncolor1, ncolor2, twocolors);
  1383.                     curcolors[ toupper(basec) - ' ']= ncolor1;
  1384.                     if (twocolors) ncolor1= ncolor2;
  1385.                     curcolors[ tolower(basec) - ' ']= ncolor1;    
  1386.                     }
  1387.                 }
  1388.             MemFree(line);
  1389.             }
  1390.         }
  1391.     MemFree(linelist);
  1392.  
  1393.     
  1394.     Nlm_SetColor(savecolor);
  1395.  
  1396.     done= true; // !! need some test of acurrate read !!
  1397.     if (done) {
  1398.         fState= kOkay;
  1399.         }
  1400.     else fState= kNodata;
  1401. }
  1402.  
  1403.  
  1404.     // make color palette like these into class
  1405.     // w/ file open/save methods, dialog choose color method
  1406.     // simplest dialog -- use r,g,b and gray switches
  1407.  
  1408. //static
  1409. void DBaseColors::InitColors() 
  1410. {
  1411.         // a static method for static vars
  1412.         // should call this Init routine from some local initializer class at startup
  1413.         // can't use the const values above -- not same for diff win systems
  1414.         //Nlm_SelectColor (Nlm_Uint1 red, Nlm_Uint1 green, Nlm_Uint1 blue)
  1415.         // ^^ this is safe for all win sys    
  1416.     colorVal savecolor= Nlm_GetColor();
  1417.     Nlm_SelectColor(   0,   0,   0); kBlack= Nlm_GetColor();
  1418.     Nlm_SelectColor( 255, 255, 255); kWhite= Nlm_GetColor();
  1419.     Nlm_SelectColor( 255,   0,   0); kRed= Nlm_GetColor();
  1420.     Nlm_SelectColor(   0, 255,   0); kGreen= Nlm_GetColor();
  1421.     Nlm_SelectColor(   0,   0, 255); kBlue= Nlm_GetColor();
  1422.     Nlm_SelectColor( 255, 255,   0); kYellow= Nlm_GetColor();
  1423.     Nlm_SelectColor( 255,   0, 255); kMagenta= Nlm_GetColor();
  1424.     Nlm_SelectColor(   0, 255, 255); kCyan= Nlm_GetColor();
  1425.     Nlm_SelectColor( 200,  89,  15); kOrange= Nlm_GetColor();
  1426.     Nlm_SelectColor(  31, 200,  31); kGreen1= Nlm_GetColor();
  1427.     Nlm_SelectColor( 127, 127, 127); kGray= Nlm_GetColor();
  1428.     Nlm_SelectColor( 191, 191, 191); kLtGray= Nlm_GetColor();
  1429.     Nlm_SelectColor(  63,  63,  63); kDkGray= Nlm_GetColor();
  1430.     Nlm_SetColor(savecolor);
  1431.     
  1432.     char ch;
  1433.     for (ch= ' '; ch <= '~'; ch++) { 
  1434.         gAAcolors[ch-' ']= kBlack; 
  1435.         gNAcolors[ch-' ']= kBlack; 
  1436.         }
  1437.     gNAcolors['A'-' ']= kRed;      
  1438.     gNAcolors['a'-' ']= kRed;
  1439.     gNAcolors['C'-' ']= kBlue;     
  1440.     gNAcolors['c'-' ']= kBlue;
  1441.     gNAcolors['G'-' ']= kGreen1; 
  1442.     gNAcolors['g'-' ']= kGreen1;
  1443.     gNAcolors['T'-' ']= kOrange;  
  1444.     gNAcolors['t'-' ']= kOrange;
  1445.     gNAcolors['U'-' ']= kOrange;
  1446.     gNAcolors['u'-' ']= kOrange;
  1447. }
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454. // class DSeqStyle
  1455.  
  1456. short DStyleTable::fState= DStyleTable::kUnread;
  1457. char* DStyleTable::fType= "seqmasks";
  1458. char* DStyleTable::fSection= "data";
  1459. char* DStyleTable::fDefaultvalue= "tables:seqmasks.table";
  1460. DList* DStyleTable::fStyles= NULL;
  1461. DSeqStyle DStyleTable::fLaststyle;
  1462. char    DStyleTable::fLastch= 0;
  1463. char* DStyleTable::fToprow = NULL;
  1464. long    DStyleTable::fToprowlen= 0;
  1465.  
  1466.  
  1467. DSeqStyle::DSeqStyle() :
  1468.     name(NULL), description(NULL),
  1469.     fontname(NULL),fontsize(10), font(NULL),
  1470.     bold(false), italic(false), uline(false), uppercase(false), lowercase(false),
  1471.     dofontpat(false),invertcolor(false), framestyle(kFrameSolid),
  1472.     fontcolor(0), backcolor(0), framecolor(0), 
  1473.     doframecolor(false), dofontcolor(false), dobackcolor(false),
  1474.     repeatchar(0),frame(kFramenone)
  1475. {
  1476.     MemFill(fontpattern,0,sizeof(fontpattern));
  1477. }
  1478.  
  1479.  
  1480. DSeqStyle::~DSeqStyle()
  1481. {
  1482.     MemFree( name);
  1483.     MemFree( description);
  1484.     MemFree( fontname);
  1485. }
  1486.  
  1487. void DSeqStyle::GetFont()
  1488. {
  1489.     if (fontname) 
  1490.         font= Nlm_GetFont( fontname, fontsize, bold, italic, uline, NULL);
  1491.     if (dofontpat && !dobackcolor) {
  1492.         dobackcolor= true;
  1493.         backcolor= 0; // black!? always or not?
  1494.         }
  1495. }
  1496.  
  1497. DObject* DSeqStyle::Clone()  
  1498. {    
  1499.     DSeqStyle* astyle= (DSeqStyle*) DObject::Clone();
  1500.     astyle->name= StrDup( name);
  1501.     astyle->description= StrDup( description);
  1502.     astyle->fontname= StrDup( fontname);
  1503.     return astyle;
  1504. }
  1505.  
  1506.  
  1507.  
  1508. Nlm_Boolean DStyleTable::NotAvailable()
  1509. {
  1510.     if (fState == kUnread) {
  1511.         char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  1512.         if (tablefile) {
  1513.             ReadTable( tablefile);
  1514.             if (fState != kOkay) {
  1515.                 DLocateFile* win= new DLocateFile("Could not read table file '%s'", tablefile);
  1516.                 if (win->PoseModally()) {
  1517.                     ReadTable( win->fName);
  1518.                     if (fState == kOkay)
  1519.                         gApplication->SetPref( win->fName, fType, fSection); //??
  1520.                     }
  1521.                 delete win;
  1522.                 }
  1523.             }
  1524.         else fState= kNodata;
  1525.         if (fState != kOkay) Message(MSG_OK,"Could not read table file '%s'",tablefile);
  1526.         MemFree( tablefile);
  1527.         }
  1528.     return (fState != kOkay);
  1529. }
  1530.  
  1531. void DStyleTable::Initialize(char* type, char* section, char* defaultvalue)
  1532. {
  1533.     fState= kUnread;
  1534.     fType= type;
  1535.     fSection= section;
  1536.     fDefaultvalue= defaultvalue;
  1537.     fStyles= new DList();
  1538.     fLastch= 0;
  1539.     fToprow = NULL;
  1540.     fToprowlen= 0;
  1541. }
  1542.  
  1543. void DStyleTable::ReadTable( char* tableFile)
  1544. {
  1545.      DFile aFile( tableFile, "r");
  1546.     ReadTable( &aFile);
  1547. }
  1548.  
  1549. void DStyleTable::ReadTable(DFile* aFile)
  1550. {
  1551.     Boolean done= false;
  1552.     short      iline, nlines = 0;
  1553.     char    * line;
  1554.      char ** linelist;
  1555.     DSeqStyle    *    astyle = NULL;
  1556.     char            * cp;
  1557.     Boolean     twocolors;
  1558.     colorVal    ncolor1, ncolor2;
  1559.     
  1560.     //fState= kNodata;
  1561.     if (!aFile || !aFile->Exists()) return;
  1562.     colorVal savecolor= Nlm_GetColor();    
  1563.     
  1564.     //fStyles->FreeAllObjects();  // MEM LEAK !
  1565.     {
  1566.     long i, n= fStyles->GetSize();
  1567.     for (i=0; i<n; i++) {
  1568.         DSeqStyle* ast= (DSeqStyle*) fStyles->At(i);
  1569.         delete ast;
  1570.         }
  1571.     fStyles->DeleteAll();
  1572.     }
  1573.     
  1574.     aFile->Open("r");
  1575.      linelist= Dgg_ReadDefaultPrefs( aFile->fFile, &nlines);
  1576.     
  1577.     for (iline= 0; iline<nlines; iline++) {
  1578.         line= linelist[iline];
  1579.         if (line && *line) {
  1580.         
  1581.             if (*line == '[') { // sect name 
  1582.                 if (astyle) { astyle->GetFont(); fStyles->InsertLast(astyle); }  // save last one
  1583.                 astyle= new DSeqStyle();
  1584.                 cp= StrChr(line,']'); if (cp) *cp= 0;
  1585.                 astyle->name= StrDup(line+1); // ?? or do we use a "name=" variable?
  1586.                 }
  1587.                 
  1588.             else if (*line == ';') { // skip comment
  1589.                 }
  1590.                 
  1591.             else if (astyle) {
  1592.                 char* val= StrChr(line, '=');
  1593.                 if (val) {
  1594.                     *val++= 0;
  1595.                     while (isspace(*val)) val++;
  1596.                     
  1597.                     if (StrNICmp(line,"descr",5)==0) {
  1598.                         astyle->description= StrDup(val);
  1599.                         }
  1600.                     else if (StrNICmp(line,"repeat",6)==0) {
  1601.                         astyle->repeatchar= *val;
  1602.                         }
  1603.                     else if (StrNICmp(line,"frame",5)==0) {
  1604.                         if (StrNICmp(val,"box",3)==0) astyle->frame= DSeqStyle::kFramebox ;
  1605.                         else if (StrNICmp(val,"oval",3)==0) astyle->frame= DSeqStyle::kFrameoval ;
  1606.                         else if (StrNICmp(val,"round",3)==0) astyle->frame= DSeqStyle::kFramerrect ;
  1607.                         }
  1608.                     else if (StrNICmp(line,"boxstyle",5)==0) {
  1609.                         if (StrNICmp(val,"dashed",3)==0) astyle->framestyle= DSeqStyle::kFrameDashed ;
  1610.                         else if (StrNICmp(val,"dotted",3)==0) astyle->framestyle= DSeqStyle::kFrameDotted ;
  1611.                         else if (StrNICmp(val,"solid",3)==0) astyle->framestyle= DSeqStyle::kFrameSolid ;
  1612.                         else if (StrNICmp(val,"dark",3)==0) astyle->framestyle= DSeqStyle::kFrameDark ;
  1613.                         else if (StrNICmp(val,"medium",3)==0) astyle->framestyle= DSeqStyle::kFrameMedium ;
  1614.                         else if (StrNICmp(val,"light",3)==0) astyle->framestyle= DSeqStyle::kFrameLight ;
  1615.                         }
  1616.                     else if (StrNICmp(line,"style",5)==0) {
  1617.                         char* delims= ",;\t ";
  1618.                         char* word = StrTok(val, delims);
  1619.                         while (word) {
  1620.                             if (StrNICmp(word,"bold",3)==0) astyle->bold= true ;
  1621.                             else if (StrNICmp(word,"italic",3)==0) astyle->italic= true ;
  1622.                             else if (StrNICmp(word,"underline",3)==0) astyle->uline= true ;
  1623.                             else if (StrNICmp(word,"uppercase",3)==0) astyle->uppercase= true ;
  1624.                             else if (StrNICmp(word,"lowercase",3)==0) astyle->lowercase= true ;
  1625.                             else if (StrNICmp(word,"box",3)==0) astyle->frame= DSeqStyle::kFramebox ;
  1626.                             else if (StrNICmp(word,"frame",3)==0) astyle->frame= DSeqStyle::kFramebox ;
  1627.                             else if (StrNICmp(word,"invertcolor",3)==0) astyle->invertcolor= true ;
  1628.                             word= StrTok( NULL, delims);
  1629.                             }
  1630.                         }
  1631.                     else if (StrNICmp(line,"fontcolor",7)==0) {
  1632.                         ::ReadColors( val, ncolor1, ncolor2, twocolors);
  1633.                         astyle->dofontcolor= true;
  1634.                         astyle->fontcolor= ncolor1;
  1635.                         }
  1636.                     else if (StrNICmp(line,"backcolor",7)==0) {
  1637.                         ::ReadColors( val, ncolor1, ncolor2, twocolors);
  1638.                         astyle->dobackcolor= true;
  1639.                         astyle->backcolor= ncolor1;
  1640.                         }
  1641.                     else if (StrNICmp(line,"framecolor",7)==0 
  1642.                                 || StrNICmp(line,"boxcolor",6)==0) {
  1643.                         ::ReadColors( val, ncolor1, ncolor2, twocolors);
  1644.                         astyle->doframecolor= true;
  1645.                         astyle->framecolor= ncolor1;
  1646.                         }
  1647.                     else if (StrNICmp(line,"fontnam",7)==0) {
  1648.                         astyle->fontname= StrDup(val);
  1649.                         }
  1650.                     else if (StrNICmp(line,"fontsiz",7)==0) {
  1651.                         astyle->fontsize= atol(val);
  1652.                         }
  1653.                     else if (StrNICmp(line,"fillpat",7)==0  
  1654.                               || StrNICmp(line,"fontpat",7)==0) {
  1655.                         astyle->dofontpat= true;
  1656.                         char * pat= astyle->fontpattern;
  1657.                       sscanf( val, "%li %li", pat, pat+4);  
  1658.                         }
  1659.  
  1660.                     }
  1661.                 }
  1662.             MemFree(line);
  1663.             }
  1664.         }
  1665.     MemFree(linelist);
  1666.     if (astyle) { astyle->GetFont(); fStyles->InsertLast(astyle); }  // save last one
  1667.     Nlm_SetColor(savecolor);
  1668.  
  1669.     done= true; // !! need some test of acurrate read !!
  1670.     if (done)  fState= kOkay;
  1671.     else fState= kNodata;
  1672. }
  1673.  
  1674.  
  1675. // static
  1676. void DStyleTable::TableChoice()
  1677. {
  1678.     char * title = "Sequence Style Table";
  1679.     char * desc = 
  1680. "[mask1]"LINEEND
  1681. "description=This is my first mask"LINEEND
  1682. "style=bold,italic,box,underline,uppercase/lowercase,invertcolor"LINEEND
  1683. "repeatchar=. ; use if you want mult-align repeated chars set to this"LINEEND
  1684. "fontname=Times"LINEEND
  1685. "fontsize=12"LINEEND
  1686. "fontcolor=0xff0000"LINEEND
  1687. "backcolor=0x80e0e0"LINEEND
  1688. "boxcolor=0x00ff00"LINEEND
  1689. "fillpattern=0xffaa8877 0xccddeeff ; use 2 hex-long values for this 8-byte pattern"LINEEND
  1690. "[anothermask]"LINEEND
  1691. "description=my second mask"LINEEND
  1692. "; ... etc ..."LINEEND
  1693.  
  1694.     char * tablefile= gApplication->GetFilePref( fType, fSection, fDefaultvalue);
  1695.     DTableChoiceDialog* win= new DTableChoiceDialog(title,desc,tablefile);
  1696.     if (win->PoseModally()) {
  1697.         ReadTable( win->fFile);
  1698.         if (fState != kOkay) {
  1699.             Message(MSG_OK, "Table wasn't properly loaded.  Please try again");
  1700.             }
  1701.         else if (win->fSetPref)
  1702.             gApplication->SetPref((char*)win->fFile->GetName(), fType, fSection);
  1703.         }
  1704.     MemFree( tablefile);
  1705.     delete win;
  1706. }
  1707.  
  1708.  
  1709. void DStyleTable::StartDraw(char* toprowbases, long maxrow)
  1710. {
  1711.     fToprow= toprowbases; // any need to dup it?
  1712.     fToprowlen= maxrow;
  1713.     fLastch= 0;
  1714. }
  1715.  
  1716. void DStyleTable::EndDraw()
  1717. {
  1718.     fToprow= NULL;
  1719.     fLaststyle.ClearDrawing();
  1720.     fLastch= 0;
  1721. }
  1722.  
  1723. void DSeqStyle::ClearDrawing()
  1724. {
  1725.         // reverse the draw screen state
  1726.     if (font) ; // set saved font !?
  1727.     font= NULL;
  1728.     //if (invertcolor) Nlm_InvertColors(); // do before Black()
  1729.     Nlm_Black();
  1730.     fontcolor= 0; // == black
  1731.     if (dobackcolor) ; //??
  1732.     backcolor= 0;
  1733.     if (dofontpat) Nlm_Solid();
  1734.     dofontpat= false;
  1735. }
  1736.  
  1737. void DStyleTable::DrawBaseWithStyle( char ch, long baseindex, short maskval,     
  1738.                                                                       Nlm_RecT&    crec, short atrow)
  1739. {
  1740.     //short maskval= aseq->MaskAt(baseindex, masklevel);
  1741.     DSeqStyle* style= NULL;
  1742.     if (maskval) style= (DSeqStyle*) fStyles->At(maskval-1);
  1743.     if (!style) {
  1744.         Nlm_PaintChar(ch);
  1745.         return;
  1746.         }
  1747.         
  1748.     if (style->repeatchar && atrow>0 && fToprow && baseindex<fToprowlen && ch == fToprow[baseindex]) 
  1749.         ch= style->repeatchar;
  1750.     if (style->uppercase) ch= toupper(ch);
  1751.     else if (style->lowercase) ch= tolower(ch);
  1752.     
  1753.     if (style->font && (style->font != Nlm_fontInUse || style->font != fLaststyle.font)) 
  1754.         Nlm_SelectFont(style->font);  
  1755.     if (style->dofontcolor) {
  1756.         //if (style->fontcolor != fLaststyle.fontcolor) 
  1757.         Nlm_SetColor(style->fontcolor);
  1758.         }
  1759.     else {
  1760.         // !! Fix this -- pass "colors" param
  1761.         //if (ch!=fLastch) Nlm_SetColor( colors[ch-' ']);
  1762.         }
  1763.         
  1764.     if (style->invertcolor && !fLaststyle.invertcolor) Nlm_InvertColors();
  1765.     // ?? &/or Nlm_InvertRect( &crec);
  1766.     // #define  ShadeInvert()  { PaintRect(myRect);    TextMode(srcBIC); }
  1767.     // if (style->dobackcolor) { Nlm_SetColor(style->backcolor); Nlm_PaintRect(&crec);    TextMode(srcBIC); } //???
  1768.     // if (style->dofontpat) Dgg_PenPattern(fontpattern);  
  1769.     
  1770.     Nlm_PaintChar(ch);
  1771.     
  1772.     if (style->frame) switch (style->frame) {
  1773.         case DSeqStyle::kFramebox:     Nlm_FrameRect( &crec); break;
  1774.         case DSeqStyle::kFrameoval:  Nlm_FrameOval( &crec); break;
  1775.         case DSeqStyle::kFramerrect: Nlm_FrameRoundRect( &crec, 4,4); break;
  1776.         default: break;
  1777.         }
  1778.         
  1779.     fLastch= ch;
  1780.     fLaststyle= *style;
  1781. }            
  1782.  
  1783.  
  1784.  
  1785.